import { OrderedSet } from 'immutable'

/**
 * 实现通用的“全选/反选”逻辑
 */
export function useChooseAll<Inst, Id>({
  list,
  getId,
  choosed,
  setChoosed,
  keep = true,
}: {
  list: Inst[]
  getId: (instance: Inst) => Id
  choosed: OrderedSet<Id>
  setChoosed: (ids: OrderedSet<Id>) => void
  // 若为 true，list 里没有，但 choosed 里有的选项会保留在 choosed 里，反选、取消选项都不会影响它；
  // 否则任意操作都会导致它们被清除
  // 对于支持筛选的场景，可能全选/反选等操作只想对筛选出来的选项生效，不想影响外界的其他选项
  keep?: boolean
}) {
  // 是否有任一选项被选中
  const hasChoosed = useMemo(
    () => list.some(inst => choosed.has(getId(inst))),
    [list, choosed, getId],
  )
  // 是否所有选项都被选中
  const allChoosed = useMemo(
    () => list.every(inst => choosed.has(getId(inst))),
    [list, choosed, getId],
  )

  // 全选
  const chooseAll = useCallback(() => {
    if (keep) {
      setChoosed(choosed.concat(list.map(getId)))
    } else {
      setChoosed(OrderedSet(list.map(getId)))
    }
  }, [list, getId, choosed, setChoosed, keep])

  // 反选
  const chooseReverse = useCallback(() => {
    if (keep) {
      let set = choosed
      list.forEach(inst => {
        const id = getId(inst)
        set = set.has(id) ? set.delete(id) : set.add(id)
      })
      setChoosed(set)
    } else {
      const filtered = list.map(getId).filter(id => !choosed.has(id))
      setChoosed(OrderedSet(filtered))
    }
  }, [list, getId, choosed, setChoosed, keep])

  // 全部取消选择
  const clearChoose = useCallback(() => {
    if (keep) {
      let set = choosed
      list.forEach(inst => {
        set = set.delete(getId(inst))
      })
      setChoosed(set)
    } else {
      setChoosed(OrderedSet())
    }
  }, [list, getId, choosed, setChoosed, keep])

  // 全选 Checkbox 的 props
  const chooseAllProps = useMemo(
    () => ({
      checked: allChoosed,
      indeterminate: hasChoosed && !allChoosed,
      onClick: allChoosed ? clearChoose : chooseAll,
    }),
    [allChoosed, hasChoosed, clearChoose, chooseAll],
  )

  return {
    hasChoosed,
    allChoosed,
    chooseAll,
    chooseReverse,
    clearChoose,
    chooseAllProps,
  }
}
